#include "../GlobalGameData.h"
#include "DTask.h"

using namespace DeepClasses;


DeepClasses::DTask::DTask()
{
	m_next=NULL;
	m_curTask = DTASK_unknown;
	m_owner=NULL;
}

DeepClasses::DTask::~DTask()
{

}

int DeepClasses::DTask::Tick()
{
	return DE_OK;
}

DeepClasses::DTskIdle::DTskIdle()
{
	m_curTask = DTASK_idle;
}

DeepClasses::DTskIdle::~DTskIdle()
{
	
}

int DeepClasses::DTskIdle::Tick()
{
	if (m_owner->m_state.hunger<m_owner->m_properties.hunger_max/3)
	{
		BOOST_FOREACH(DItem* i,gameData.m_world->m_items)
		{
			if(i->m_isFood)
			{
				DTskAct* tact = new DTskAct();
				tact->m_targetPoint = i->m_pos;
				m_owner->InsertTask(tact);
				DTskFindPath* tpath = new DTskFindPath();
				tpath->m_targetPoint = i->m_pos;
				m_owner->InsertTask(tpath);
			}
		}
	}

	return DE_OK;
}

DeepClasses::DTskFindPath::DTskFindPath() : m_solver(DTskFindPath::SolverFunc)
{
	m_curTask = DTASK_findpath;
	m_mode = FP_Start;
	m_stopSolver=false;
}


DeepClasses::DTskFindPath::~DTskFindPath()
{

}

int DeepClasses::DTskFindPath::Tick()
{
	switch(m_mode)
	{
	case FP_Start:
		m_mode = FP_Wait;
		m_stopSolver=false;
		m_solver.Start(this);
		break;
	case FP_Wait:
		break;
	case FP_Walk:
		break;
	}
	return DE_OK;
}

int DeepClasses::DTskFindPath::SolverFunc( void* context )
{
	DTskFindPath* T = (DTskFindPath*)context;

	
	std::list<TLocationPath*> openList;
	std::list<TLocationPath*> closedList;
	TLocationPath* curpos = new TLocationPath(T->m_owner->m_pos.m_i,T->m_owner->m_pos.m_j,T->m_owner->m_pos.m_z);
	

	while(T->m_stopSolver==false)
	{
		

		closedList.push_front(curpos);
		

		if(*curpos==T->m_targetPoint)
		{
			while(curpos->m_pathParent!=NULL)
			{
				DItem* m = new DItem(L"marker", '.',0x0f);
				m->Place(*curpos);
				gameData.m_world->m_items.push_back(m);
				curpos = curpos->m_pathParent;
			}
			break;
		}
		
		T->TestCells(openList,closedList,curpos);
		if(openList.empty())
		{
			break;
		
		}
		else
		{
			curpos = openList.back();

			openList.pop_back();
			/*DCell* cell = gameData.m_world->m_map.GetCellAt(*curpos);
			if(cell!=NULL)
			{
				std::list<DObject*> markers;
				cell->GetObjectsByName(markers,L"marker");
				BOOST_FOREACH(DObject* m, markers)
				{
					m->Remove();
				}
					
			}*/
		}
		SexyThread::Idle(1);
		
	}

	

	return DE_OK;
}

void DeepClasses::DTskFindPath::AddToOpenList(std::list<TLocationPath*>& list, TLocationPath* loc, TLocationPath* curloc)
{
	bool stop=false;
	
	TLocationPath* trg = NULL;
	std::list<TLocationPath*>::iterator it = list.begin();
	while(it!=list.end())
	{
		if(*it==loc)
		{
			trg = *it;
			list.erase(it);
			delete loc;
			break;
		}
		it++;
	}

	if(trg==NULL)
	{
		trg=loc;
		//DItem* m = new DItem(L"marker", 'p',0x0f);
		//m->Place(*loc);
	}

	trg->m_pathG=curloc->m_pathG+1;
	trg->m_pathF=trg->m_pathG
		+abs(m_targetPoint.m_i-trg->m_i)
		+abs(m_targetPoint.m_j-trg->m_j)
		+abs(m_targetPoint.m_z-trg->m_z);
	trg->m_pathParent=curloc;	
	
	it = list.begin();
	while(it!=list.end())
	{
		if(((*it)->m_pathF)<(trg->m_pathF))
		{
			list.insert(it,trg);
			break;
		}
		it++;
	}
	if(it==list.end())
		list.push_back(trg);
	
}
int DeepClasses::DTskFindPath::TestCells( std::list<TLocationPath*>& openList,std::list<TLocationPath*>& closedList,TLocationPath* curloc )
{
	DMap* m = &gameData.m_world->m_map;
	//DCell* c;
	TLocationPath* loc;
	loc = curloc->PT_ShiftAlloc(1,0,0);
	if(IsPassable(loc)  &&!IsInList(closedList,loc))
	{
		AddToOpenList(openList,loc,curloc);
		loc = curloc->PT_ShiftAlloc(0,1,0);
	}
	else
	{
		loc->PT_Shift(-1,1,0);
	}

	if(IsPassable(loc)  &&!IsInList(closedList,loc))
	{
		AddToOpenList(openList,loc,curloc);
		loc = curloc->PT_ShiftAlloc(-1,0,0);
	}
	else
	{
		loc->PT_Shift(-1,-1,0);
	}
	
	if(IsPassable(loc) &&!IsInList(closedList,loc))
	{
		AddToOpenList(openList,loc,curloc);
		loc = curloc->PT_ShiftAlloc(0,-1,0);
	}
	else
	{
		loc->PT_Shift(1,-1,0);
	}

	if(IsPassable(loc) &&!IsInList(closedList,loc))
	{
		AddToOpenList(openList,loc,curloc);
	}
	else
	{
		delete loc;
	}

	return DE_OK;
}

bool DeepClasses::DTskFindPath::IsInList(std::list<TLocationPath*>& list, TLocationPath* loc)
{
	BOOST_FOREACH(TLocation* i,list)
	{
		if((*i)==(*loc))
			return true;
	}
	return false;
}

bool DeepClasses::DTskFindPath::IsPassable( TLocationPath* loc )
{
	DMap* m = &gameData.m_world->m_map;
	DCell* c;
	bool res = false;
	c = m->GetCellAtShift(*loc,0,0,0);
	if(c!=NULL)
	{
		if(c->m_fillMat==NULL)
		{
			if(c->m_floorMat!=NULL)
			{
				res=true;
			}
			else
			{
				DCell* b = m->GetCellAtShift(*loc,-1,0,0);
				if(b!=NULL)
				{
					if(b->m_fillMat!=NULL)
					{
						res=true;
					}
				}
			}
		}
	}
	return res;
}
DeepClasses::DTskAct::DTskAct()
{
	m_curTask = DTASK_act;
}

DeepClasses::DTskAct::~DTskAct()
{

}

int DeepClasses::DTskAct::Tick()
{
	return DE_OK;
}
